package com.lyy.component;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.lyy.result.Result;
import com.lyy.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
 * @author Liangyaoyun
 */
@SuppressWarnings("all")
@Slf4j
@RestControllerAdvice(basePackages = {"com.lyy.controller"})
public class ResultAdvice implements ResponseBodyAdvice<Object> {

    /** 该方法在控制方法返回数据前执行 */
    @Override
    public boolean supports(MethodParameter param, Class<? extends HttpMessageConverter<?>> aClass) {
        // 仅在该方法返回true时，才会进入 beforeBodyWrite 方法进行下一步操作
        return true;
    }

    /** 该方法在控制方法响应数据前执行 */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {

        // 若返回值是null，则直接返回失败信息
        if(ObjectUtil.isNull(o)){
            return new Result(ResultCode.FAILED, "响应数据为空");
        }

        // 若Jackson使用字符串转换器，使用JSON封装一下再直接返回字符串，避免爆发转换异常
        if (aClass == StringHttpMessageConverter.class) {
            return JSONUtil.toJsonStr(o);
        }

        // 若返回值已经是Result类型则直接返回
        if(o instanceof Result){
            return o;
        }

        // 若返回值是Boolean类型，则返回成功或失败的信息
        if(o instanceof Boolean){
            boolean result = (Boolean)o;
            return result ? new Result(ResultCode.SUCCESS) : new Result(ResultCode.FAILED, "操作失败");
        }

        // 将返回值封装为Result类型后响应
        return new Result(o);
    }

}
